package com.bkhech.home.practice.spring.databuffer;

import io.netty.buffer.PooledByteBufAllocator;
import org.springframework.core.io.buffer.*;
import org.springframework.util.Assert;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * spring-core io 包 DataBuffer，PoolDataBuffer，DataBufferFactory接口源码解析
 * <p>
 * {@literal <a href="https://blog.csdn.net/qq_31865983/article/details/83214531">...</a>}
 *
 * @author guowm
 * @date 2023/1/30
 */
public class DataBufferDemo {

    public static void main(String[] args) throws IOException {
//        writeAndRead();
        retainAndRelease();
    }

    private static void retainAndRelease() {
        final NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new PooledByteBufAllocator());
        // NettyDataBuffer是PooledDataBuffer的唯一实现，基于Netty 的ByteBuf实现。
        //  PooledDataBuffer继承DataBuffer接口，增加了引用计数的方法，
        //  保留方法（retain）将引用计数增加1。释放方法（release）将计数减1，并在计数达到0时释放缓冲区的内存
        final NettyDataBuffer buffer = nettyDataBufferFactory.allocateBuffer(4);

        buffer.retain();

        boolean result = buffer.release();
        System.out.println(result);

        result = buffer.release();
        System.out.println(result);
    }

    private static void writeAndRead() throws IOException {
        DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
        final DataBuffer buffer = dataBufferFactory.allocateBuffer(2);
        buffer.write(new byte[]{'a', 'b', 'c'});
        printBuffer(buffer);

        final int index = buffer.indexOf(value -> value == 'c', 1);
        System.out.println("index --> " + index);

//        final byte ch = buffer.read();
//        Assert.isTrue('a' == ch, "ch is " + ch);

        buffer.readPosition(2);
        final byte ch = buffer.read();
        Assert.isTrue('c' == ch, "ch is " + ch);

        buffer.write((byte) 'd');
        buffer.write((byte) 'e');

        byte[] result = new byte[2];
        buffer.read(result);
        Assert.isTrue(Arrays.equals(new byte[]{'d', 'e'}, result), "result is " + Arrays.toString(result));

        printBuffer(buffer);


        ByteBuffer buffer2 = ByteBuffer.allocate(4);
        buffer2.put((byte) '1');
        buffer2.put((byte) '2');
        buffer2.put((byte) '3');
        buffer2.put((byte) '4');
        // 设置 newPosition, 使 buffer2.remaining() 不等于 0，否则 buffer.write 写不进去
        buffer2.position(0);

        System.out.println("write before writePosition-->" + buffer);
        buffer.write(buffer2);
        System.out.println("write after writePosition-->" + buffer);

        final ByteBuffer buffer3 = buffer.asByteBuffer(4, 5);
        final byte ch3 = buffer3.get();
        Assert.isTrue('e' == ch3, "ch is " + ch3);
        System.out.println(buffer3);

        final InputStream in = buffer.asInputStream();
        in.read(result);
        System.out.println(new String(result));
//        in.read(result);
//        System.out.println(new String(result));

        DataBufferUtils.release(buffer);

        printBuffer(buffer);
    }

    private static void printBuffer(DataBuffer buffer) {
        System.out.println("capacity --> " + buffer.capacity());
        System.out.println("readPosition --> " + buffer.readPosition());
        System.out.println("writePosition --> " + buffer.writePosition());
        System.out.println("writableByteCount --> " + buffer.writableByteCount());
        System.out.println("readableByteCount --> " + buffer.readableByteCount());
    }

}
